package com.template.utils;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements ApplicationContextAware {
    /** Spring应用上下文环境 */
    private static ApplicationContext applicationContext;

    /**
     * 设置Spring应用上下文环境
     * @param applicationContext Spring应用上下文
     * @throws BeansException 如果设置过程中出现错误
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * 获取Spring应用上下文环境
     * @return 应用上下文
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 根据名称获取Spring管理的bean
     * @param name bean的名称
     * @return 指定名称的bean
     * @throws BeansException 如果获取bean时发生错误
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) getApplicationContext().getBean(name);
    }

    /**
     * 根据类型获取Spring管理的bean
     * @param clz bean的类型
     * @return 指定类型的bean
     * @throws BeansException 如果获取bean时发生错误
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) getApplicationContext().getBean(clz);
        return result;
    }

    /**
     * 检查Spring应用上下文中是否包含指定名称的bean
     * @param name bean的名称
     * @return 如果存在指定名称的bean则返回true，否则返回false
     */
    public static boolean containsBean(String name) {
        return getApplicationContext().containsBean(name);
    }

    /**
     * 判断指定名称的bean是否是单例
     * @param name bean的名称
     * @return 如果是单例则返回true，否则返回false
     * @throws NoSuchBeanDefinitionException 如果没有找到指定名称的bean
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getApplicationContext().isSingleton(name);
    }

    /**
     * 获取指定名称的bean的类型
     * @param name bean的名称
     * @return bean的类型
     * @throws NoSuchBeanDefinitionException 如果没有找到指定名称的bean
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getApplicationContext().getType(name);
    }

    /**
     * 获取指定名称的bean的所有别名
     * @param name bean的名称
     * @return bean的所有别名
     * @throws NoSuchBeanDefinitionException 如果没有找到指定名称的bean
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return getApplicationContext().getAliases(name);
    }

    /**
     * 获取当前AOP代理对象
     * @param invoker 被代理的对象
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) AopContext.currentProxy();
    }

    /**
     * 获取当前激活的所有环境配置
     * @return 所有激活的环境配置
     */
    public static String[] getActiveProfiles() {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

    /**
     * 获取当前激活的第一个环境配置
     * @return 第一个激活的环境配置，如果没有任何激活的环境配置则返回null
     */
    public static String getActiveProfile() {
        final String[] activeProfiles = getActiveProfiles();
        return activeProfiles != null && activeProfiles.length > 0 ? activeProfiles[0] : null;
    }
}